From 9f7716967ad3d53e49d73150ca1fac5a90d5362f Mon Sep 17 00:00:00 2001 From: robertl Date: Tue, 13 Sep 2005 20:11:39 +0000 Subject: [PATCH] Olaf adds Support for Navigon Mobile Navigator 5 Palm/OS files. Refactor is_fatal and lrtrim to be common code. --- gpsbabel/Makefile | 4 +- gpsbabel/README | 8 ++ gpsbabel/cst.c | 24 +---- gpsbabel/defs.h | 7 ++ gpsbabel/msroute.c | 15 --- gpsbabel/nmn5.c | 217 ++++++++++++++++++++++++++++++++++++++++++++ gpsbabel/pathaway.c | 6 -- gpsbabel/testo | 7 ++ gpsbabel/util.c | 32 +++++++ gpsbabel/vecs.c | 7 ++ 10 files changed, 286 insertions(+), 41 deletions(-) create mode 100644 gpsbabel/nmn5.c diff --git a/gpsbabel/Makefile b/gpsbabel/Makefile index 524b29bec..f89ac1f56 100644 --- a/gpsbabel/Makefile +++ b/gpsbabel/Makefile @@ -39,7 +39,7 @@ FMTS=magproto.o gpx.o geo.o mapsend.o mapsource.o garmin_tables.o \ igc.o brauniger_iq.o shape.o hiketech.o glogbook.o coastexp.o \ vcf.o overlay.o kml.o google.o lowranceusr.o an1.o tomtom.o \ tef_xml.o maggeo.o pathaway.o vitosmt.o gdb.o bcr.o coto.o \ - ignrando.o stmwpp.o msroute.o cst.o + ignrando.o stmwpp.o msroute.o cst.o nmn5.o FILTERS=position.o duplicate.o arcdist.o polygon.o smplrout.o reverse_route.o sort.o stackfilter.o trackfilter.o discard.o @@ -220,6 +220,8 @@ msroute.o: msroute.c defs.h queue.h gbtypes.h navicache.o: navicache.c defs.h queue.h gbtypes.h cet_util.h netstumbler.o: netstumbler.c defs.h queue.h gbtypes.h csv_util.h nmea.o: nmea.c defs.h queue.h gbtypes.h +nmn5.o: nmn5.c defs.h queue.h gbtypes.h coldsync/palm.h coldsync/pdb.h \ + jeeps/gpsmath.h overlay.o: overlay.c defs.h queue.h gbtypes.h grtcirc.h ozi.o: ozi.c defs.h queue.h gbtypes.h csv_util.h palmdoc.o: palmdoc.c defs.h queue.h gbtypes.h jeeps/gpsmath.h jeeps/gps.h \ diff --git a/gpsbabel/README b/gpsbabel/README index c8f1dc0f1..14d782a5a 100644 --- a/gpsbabel/README +++ b/gpsbabel/README @@ -1084,6 +1084,14 @@ THE FORMATS http://phgiraud.free.fr/CarteSurTable/CarteSurTable.htm + nmn5 + + Support for Navigon Mobile Navigator 5 Palm/OS files. + This is a route-only format. + + http://www.navigon.com + + DATA FILTERS GPSBabel supports data filtering. Data filters are invoked from diff --git a/gpsbabel/cst.c b/gpsbabel/cst.c index 264d3794a..f33582242 100644 --- a/gpsbabel/cst.c +++ b/gpsbabel/cst.c @@ -52,20 +52,6 @@ arglist_t cst_args[] = { /* helpers */ -static char * -cst_trim_buff(char *buff) -{ - char *c; - - c = buff + strlen(buff); - while ((c >= buff) && ((unsigned char)*c <= ' ')) *c-- = '\0'; - - c = buff; - while ((*c != '\0') && ((unsigned char)*c <= ' ')) c++; - - return c; -} - static void cst_add_wpt(const route_head *track, waypoint *wpt) { @@ -188,7 +174,7 @@ cst_data_read(void) char *cin = buff; line++; - cin = cst_trim_buff(buff); + cin = lrtrim(buff); if (strlen(cin) == 0) continue; if (strncmp(cin, "; ", 2) == 0) continue; @@ -224,7 +210,7 @@ cst_data_read(void) if (strncmp(cin + 2, "bitmap", 6) == 0) { - cin = cst_trim_buff(cin + 8); + cin = lrtrim(cin + 8); if (*cin != '\0') wpt->url = cst_make_url(cin); } @@ -232,13 +218,13 @@ cst_data_read(void) while (NULL != fgets(buff, sizeof(buff), fin)) { line++; - cin = cst_trim_buff(buff); + cin = lrtrim(buff); if (strcmp(cin + 2, "note") == 0) { fgets(buff, sizeof(buff), fin); line++; - cin = cst_trim_buff(buff); + cin = lrtrim(buff); if (*cin != '\0') wpt->notes = xstrdup(cin); } @@ -300,7 +286,7 @@ cst_data_read(void) { struct tm tm; - pow = cst_trim_buff(++pow); + pow = lrtrim(++pow); strptime(pow, "%Y %m %d %H:%M:%S", &tm); wpt->creation_time = mkgmtime(&tm); diff --git a/gpsbabel/defs.h b/gpsbabel/defs.h index 2dced8f30..e7a785f0a 100644 --- a/gpsbabel/defs.h +++ b/gpsbabel/defs.h @@ -523,6 +523,12 @@ void fatal(const char *, ...) __attribute__((noreturn)) #endif ; +void is_fatal(const int condition, const char *, ...); +#if __GNUC__ + __attribute__ ((__format__ (__printf__, 1, 2))) + __attribute__((noreturn)) +#endif + void warning(const char *, ...) #if __GNUC__ __attribute__ ((__format__ (__printf__, 1, 2))) @@ -595,6 +601,7 @@ char *strsub(const char *s, const char *search, const char *replace); char *gstrsub(const char *s, const char *search, const char *replace); char *xstrrstr(const char *s1, const char *s2); void rtrim(char *s); +char * lrtrim(char *s); signed int get_tz_offset(void); time_t mkgmtime(struct tm *t); time_t current_time(void); diff --git a/gpsbabel/msroute.c b/gpsbabel/msroute.c index 187e26c08..d85e96c4f 100644 --- a/gpsbabel/msroute.c +++ b/gpsbabel/msroute.c @@ -154,21 +154,6 @@ static int ole_root_sec_ct; /* local helpers */ -static void -is_fatal(const int condition, const char *fmt, ...) -{ - va_list args; - char buff[128]; - - if (condition == 0) return; - - va_start(args, fmt); - vsnprintf(buff, sizeof(buff), fmt, args); - va_end(args); - - fatal(MYNAME ": %s\n", buff); -} - static void print_buff(const char *buff, int count, const char *comment) { diff --git a/gpsbabel/nmn5.c b/gpsbabel/nmn5.c new file mode 100644 index 000000000..209289822 --- /dev/null +++ b/gpsbabel/nmn5.c @@ -0,0 +1,217 @@ +/* + + Support for Navigon Mobile Navigator Palm/OS pdb files, + + Copyright (C) 2005 Olaf Klein, o.b.klein@t-online.de + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + +*/ + +#include +#include + +#include "defs.h" +#include "coldsync/palm.h" +#include "coldsync/pdb.h" +#include "jeeps/gpsmath.h" + +#define MYNAME "nmn5" + +#define NMN5_MAGIC 0x766d6170 /* vmap */ +#define NMN5_ROUTE 0x49444154 /* IDAT */ + +FILE *fd_in; +static struct pdb *pdb_in; +static char *fname_in; + +static arglist_t nmn5_args[] = +{ + {0, 0, 0, 0, 0 } +}; + +static double +nmn5_to_degree(const int degx) +{ + int m, d, x; + double s, res; + + d = degx / 100000; + x = degx % 100000; + m = x / 1000; + x = x % 1000; + s = (double)(x) / 10; + + GPS_Math_DegMinSec_To_Deg(d, m, s, &res); + + return res; +} + +static void +nmn5_read_data(const char *data, const size_t data_len) +{ + route_head *route; + char *cin = (char *)data; + char *cend = cin + data_len; + + route = route_head_alloc(); + route_add_head(route); + + while (cin < cend) + { + char *lend; + int len; + + lend = strchr(cin, '\x0A'); + if (lend == NULL) break; + + len = (lend - cin); + if (len > 0) + { + *lend = '\0'; + + if (case_ignore_strncmp(cin, "Wegname=", 8) == 0) /* This only works with the german release */ + { /* test-data created with other releases are welcome */ + cin += 8; + if (*cin != '\0') + route->rte_name = xstrdup(cin); + } + else if (case_ignore_strncmp(cin, "Fahrzeit=", 9) == 0) + { + } + else if (case_ignore_strncmp(cin, "Kosten=", 7) == 0) + { + } + else + { + char *buff, *comma; + + /* now we are looking for a sequence like 0,1 NE (123456,654321) */ + + buff = xmalloc(strlen(cin) + 1); /* safe target space for sscanf( ... */ + + comma = cin; + while ((comma = strchr(comma, ','))) + { + int i, xlat, xlon; + waypoint *wpt; + char *cx; + + comma++; + + if (isdigit(*comma) == 0) continue; + if (isdigit(*(comma - 2)) == 0) continue; + + if (4 != sscanf(comma, "%d %s (%d,%d)", &i, buff, &xlon, &xlat)) continue; + if (strchr("NESW", *buff) == NULL) continue; /* north, east, ... */ + + cx = comma - 2; /* go left over delta distance */ + while (isdigit(*cx) != 0) *cx-- = '\0'; + cin = lrtrim(cin); + + for (i = 0; i < 2; i++) /* skip time and distance at start of line */ + { + cin = strchr(cin, ' '); + cin = lrtrim(cin); + } + + wpt = waypt_new(); + + wpt->latitude = nmn5_to_degree(xlat); + wpt->longitude = nmn5_to_degree(xlon); + wpt->description = xstrdup(cin); + + cx = strchr(comma, ')'); /* find tailing notes after the coordinates */ + if (cx != NULL) + { + char *tail = lrtrim(++cx); + if (*tail != '\0') + { + wpt->notes = xstrdup(tail); + } + } + if (*cin != '-') + waypt_add(waypt_dupe(wpt)); + + route_add_wpt(route, wpt); + + break; + } + xfree(buff); + } + + } + cin = lend + 1; + } +} + +/* ============================================================================================ + * &&& gobal callbacks &&& + * ----------------------------------------------------------------------------------------- */ + +static void nmn5_rd_init(const char *fname) +{ + fname_in = xstrdup(fname); + fd_in = xfopen(fname, "rb", MYNAME); +} + +static void nmn5_rd_deinit(void) +{ + fclose(fd_in); + xfree(fname_in); +} + +static void nmn5_read(void) +{ + struct pdb_record *pdb_rec = NULL; + + + pdb_in = pdb_Read(fileno(fd_in)); + is_fatal((pdb_in == NULL), "read failed."); + + is_fatal((pdb_in->creator != NMN5_MAGIC), /* identify the database */ + "Not a NMN5 pdb file (0x%08x).", pdb_in->creator); + + is_fatal((pdb_in->version != 0), /* only version "0" currently seen and tested */ + "This file is from an unsupported version (%d) of NMN5 and is unsupported.", pdb_in->version + 5); + + is_fatal((pdb_in->type != NMN5_ROUTE), + "Unknown pdb data type (0x%08x).", pdb_in->type); + + for (pdb_rec = pdb_in->rec_index.rec; pdb_rec; pdb_rec=pdb_rec->next) + { + char *data = (char *)pdb_rec->data; + + if (be_read16(data) == 0) + nmn5_read_data(data + 3, pdb_rec->data_len - 3); + } + free_pdb(pdb_in); +} + +/* ======================================================================================= */ + +ff_vecs_t nmn5_vecs = { + ff_type_file, + { ff_cap_read, ff_cap_none, ff_cap_read }, /* real route + emulated waypoints */ + nmn5_rd_init, + NULL, + nmn5_rd_deinit, + NULL, + nmn5_read, + NULL, + NULL, + nmn5_args, + CET_CHARSET_MS_ANSI, 1 /* CET-REVIEW */ +}; diff --git a/gpsbabel/pathaway.c b/gpsbabel/pathaway.c index 3e06745a0..909b3e25a 100644 --- a/gpsbabel/pathaway.c +++ b/gpsbabel/pathaway.c @@ -69,12 +69,6 @@ static arglist_t ppdb_args[] = {0, 0, 0, 0, 0 } }; -static void -is_fatal(int is, const char *msg, ... ) -{ - if (is) fatal(MYNAME ": %s\n", msg); -} - #define PPDB_DEBUG 1 #if PPDB_DEBUG diff --git a/gpsbabel/testo b/gpsbabel/testo index 819d5698a..6b2223fbf 100755 --- a/gpsbabel/testo +++ b/gpsbabel/testo @@ -866,4 +866,11 @@ rm -f ${TMPDIR}/cst-* ${PNAME} -i cst -f reference/route/cst-sample.cst -o gpx -F ${TMPDIR}/cst-sample.gpx compare ${TMPDIR}/cst-sample.gpx reference/route/cst-sample.gpx +# +# Navigon Mobile Navigator 5 .pdb (read-only) +# +rm -f ${TMPDIR}/nmn5-sample* +# ${PNAME} -i nmn5 -f reference/route/nmn5-sample.pdb -o gpx -F ${TMPDIR}/nmn5-sample.gpx +# compare ${TMPDIR}/nmn5-sample.gpx reference/route/nmn5-sample.gpx + exit 0 diff --git a/gpsbabel/util.c b/gpsbabel/util.c index ad4edf439..48ec95b45 100644 --- a/gpsbabel/util.c +++ b/gpsbabel/util.c @@ -311,6 +311,23 @@ rtrim(char *s) } } +/* + * Like trim, but trims whitespace from both beginning and end. + */ +char * +lrtrim(char *buff) +{ + char *c; + + c = buff + strlen(buff); + while ((c >= buff) && ((unsigned char)*c <= ' ')) *c-- = '\0'; + + c = buff; + while ((*c != '\0') && ((unsigned char)*c <= ' ')) c++; + + return c; +} + /* * Like strcmp, but case insensitive. Like Berkeley's strcasecmp. */ @@ -362,6 +379,21 @@ fatal(const char *fmt, ...) exit(1); } +void +is_fatal(const int condition, const char *fmt, ...) +{ + va_list args; + char buff[128]; + + if (condition == 0) return; + + va_start(args, fmt); + vsnprintf(buff, sizeof(buff), fmt, args); + va_end(args); + + fatal("%s\n", buff); +} + void warning(const char *fmt, ...) { diff --git a/gpsbabel/vecs.c b/gpsbabel/vecs.c index 40089e1f7..72f8ad066 100644 --- a/gpsbabel/vecs.c +++ b/gpsbabel/vecs.c @@ -90,6 +90,7 @@ extern ff_vecs_t ignr_vecs; extern ff_vecs_t stmwpp_vecs; extern ff_vecs_t msroute_vecs; extern ff_vecs_t cst_vecs; +extern ff_vecs_t nmn5_vecs; static vecs_t vec_list[] = { @@ -456,6 +457,12 @@ vecs_t vec_list[] = { "CarteSurTable data file", "cst" }, + { + &nmn5_vecs, + "nmn5", + "Navigon Mobile Navigator 5 .pdb", + "pdb" + }, { NULL, NULL, -- 2.30.2